package com.camera2.activity;

import android.Manifest;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.ProgressDialog;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.drawable.Drawable;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.media.Image;
import android.media.ImageReader;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.SparseIntArray;
import android.view.KeyEvent;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;
import android.widget.VideoView;
import com.camera2.frament.Frament;
import com.camera2.Utils.ByteBitmap;
import com.camera2.dao.MovieRecorder;
import com.camera2.http.SendImage;
import com.camera2.local.SaveImage;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;


public class TakePicture extends AppCompatActivity implements View.OnClickListener {

    private static final SparseIntArray ORIENTATIONS = new SparseIntArray();

    static {
        ORIENTATIONS.put(Surface.ROTATION_0, 90);
        ORIENTATIONS.put(Surface.ROTATION_90, 0);
        ORIENTATIONS.put(Surface.ROTATION_180, 270);
        ORIENTATIONS.put(Surface.ROTATION_270, 180);
    }

    private SurfaceView mSurfaceView;
    private SurfaceHolder mSurfaceHolder;
    private ImageView iv_show;
    private RelativeLayout rl_video;
    private VideoView vv_video;
    private ImageButton ib_video;
    private CameraManager mCameraManager;
    private Handler childHandler, mainHandler;
    private String mCameraID;
    private ImageReader mImageReader;
    private CameraCaptureSession mCameraCaptureSession;
    private CameraDevice mCameraDevice;


    private LinearLayout ll_imgtake;
    private LinearLayout ll_imgshow;

    private EditText et_disease;
    private String disease;


    private Button bt_takepicture;
    private Button bt_startVideo;
    private Button bt_stopVideo;
    private Button bt_picture;
    private Button bt_video;

    private MovieRecorder movieRecorder;

    //录音相关
    private MediaRecorder mr;
    private MediaPlayer mp;
    private File voiceDir;
    private File curVoiveFile;
    private Button btStartRecord;
    private Button btStartPlay;
    private ImageView iv;
    private Drawable[] micImages;

    private CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
        @Override
        public void onOpened(@NonNull CameraDevice cameraDevice) {
            mCameraDevice = cameraDevice;
            takePreview();
        }

        @Override
        public void onDisconnected(@NonNull CameraDevice cameraDevice) {
            if (null != mCameraDevice) {
                mCameraDevice.close();
                TakePicture.this.mCameraDevice = null;
            }
        }

        @Override
        public void onError(@NonNull CameraDevice cameraDevice, int i) {
            Toast.makeText(TakePicture.this, "摄像头开启失败", Toast.LENGTH_SHORT).show();
        }
    };

    private void takePreview() {
        try {
            final CaptureRequest.Builder previewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            previewRequestBuilder.addTarget(mSurfaceHolder.getSurface());
            mCameraDevice.createCaptureSession(Arrays.asList(mSurfaceHolder.getSurface(), mImageReader.getSurface()), new CameraCaptureSession.StateCallback() // ③
            {
                @Override
                public void onConfigured(CameraCaptureSession cameraCaptureSession) {
                    if (null == mCameraDevice) return;
                    mCameraCaptureSession = cameraCaptureSession;
                    try {
                        previewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
                        previewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
                        CaptureRequest previewRequest = previewRequestBuilder.build();
                        mCameraCaptureSession.setRepeatingRequest(previewRequest, null, childHandler);
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
                    Toast.makeText(TakePicture.this, "配置失败", Toast.LENGTH_SHORT).show();
                }
            }, childHandler);


        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_take);


        initView();
        initVoice();
    }

    public void initVoice() {
        voiceDir = new File(Environment.getExternalStorageDirectory(), "xiaomuyi");
        if (!voiceDir.exists()) {
            voiceDir.mkdirs();
        }
        initMediaRecorder();
        initMediaPlayer();

        btStartRecord = findViewById(R.id.button1);

        btStartRecord.setOnLongClickListener(new startRecordListener());
        btStartRecord.setOnClickListener(new stopRecordListener());

        btStartPlay = findViewById(R.id.button3);

        iv = findViewById(R.id.imageView1);
        micImages = new Drawable[]{getResources().getDrawable(R.drawable.record_animate_01),
                getResources().getDrawable(R.drawable.record_animate_02), getResources().getDrawable(R.drawable.record_animate_03),
                getResources().getDrawable(R.drawable.record_animate_04), getResources().getDrawable(R.drawable.record_animate_05),
                getResources().getDrawable(R.drawable.record_animate_06), getResources().getDrawable(R.drawable.record_animate_07),
                getResources().getDrawable(R.drawable.record_animate_08), getResources().getDrawable(R.drawable.record_animate_09),
                getResources().getDrawable(R.drawable.record_animate_10), getResources().getDrawable(R.drawable.record_animate_11),
                getResources().getDrawable(R.drawable.record_animate_12), getResources().getDrawable(R.drawable.record_animate_13),
                getResources().getDrawable(R.drawable.record_animate_14),};
    }

    private void initView() {

        findViewById(R.id.bt_album).setOnClickListener(this);

        bt_takepicture = findViewById(R.id.bt_takepicture);
        bt_takepicture.setOnClickListener(this);
        bt_startVideo = findViewById(R.id.bt_startVideo);
        bt_startVideo.setOnClickListener(this);
        bt_startVideo.setVisibility(View.GONE);
        bt_stopVideo = findViewById(R.id.bt_stopVideo);
        bt_stopVideo.setOnClickListener(this);
        bt_stopVideo.setVisibility(View.GONE);
        bt_picture = findViewById(R.id.bt_picture);
        bt_picture.setOnClickListener(this);
        bt_video = findViewById(R.id.bt_video);
        bt_video.setOnClickListener(this);
        bt_video.setVisibility(View.GONE);

        findViewById(R.id.bt_trans).setOnClickListener(this);
        findViewById(R.id.bt_submit).setOnClickListener(this);


        ll_imgshow = findViewById(R.id.ll_imgshow);
        ll_imgtake = findViewById(R.id.ll_imgtake);
        ll_imgshow.setVisibility(View.GONE);
        ll_imgtake.setVisibility(View.VISIBLE);

        et_disease = findViewById(R.id.et_disease);


        rl_video = findViewById(R.id.rl_video);
        rl_video.setVisibility(View.GONE);
        vv_video = findViewById(R.id.vv_video);
        ib_video = findViewById(R.id.ib_video);
        ib_video.setVisibility(View.GONE);
        ib_video.setOnClickListener(this);
        iv_show = findViewById(R.id.iv_show);
        iv_show.setVisibility(View.VISIBLE);
        mSurfaceView = findViewById(R.id.surface);


        mSurfaceHolder = mSurfaceView.getHolder();
        mSurfaceHolder.setKeepScreenOn(true);
        mSurfaceHolder.setKeepScreenOn(true);
        mCameraID = "" + CameraCharacteristics.LENS_FACING_FRONT;
        mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder surfaceHolder) {
                initCamera2();
            }

            @Override
            public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
            }

            @Override
            public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
                if (null != mCameraDevice) {
                    mCameraDevice.close();
                    TakePicture.this.mCameraDevice = null;
                }
            }
        });
    }

    private void initCamera2() {
        HandlerThread handlerThread = new HandlerThread("Camera2");
        handlerThread.start();
        childHandler = new Handler(handlerThread.getLooper());
        mainHandler = new Handler(getMainLooper());
//        mCameraID = "" + CameraCharacteristics.LENS_FACING_FRONT;//hou
        mImageReader = ImageReader.newInstance(1080, 1920, ImageFormat.JPEG, 50);
        mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
            @Override
            public void onImageAvailable(ImageReader imageReader) {

                Image image = imageReader.acquireNextImage();
                ByteBuffer buffer = image.getPlanes()[0].getBuffer();
                byte[] bytes = new byte[buffer.remaining()];

                buffer.get(bytes);
                final Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
                ByteBitmap bb = new ByteBitmap();
                byte[] byt = bb.Bitmap2Bytes(bitmap);
                SaveImage.saveImg(getApplicationContext(), byt);
                if (bitmap != null) {
                    ll_imgshow.setVisibility(View.VISIBLE);
                    ll_imgtake.setVisibility(View.GONE);
                    iv_show.setImageBitmap(bitmap);
                }

                takePreview();

            }
        }, mainHandler);
        mCameraManager = (CameraManager) getApplicationContext().getSystemService(Context.CAMERA_SERVICE);
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {

            return;
        }
        try {
            mCameraManager.openCamera(mCameraID, stateCallback, mainHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.bt_takepicture:
                takePicture();
                break;
            case R.id.bt_album:
                openAlbum();
                break;
            case R.id.bt_startVideo:
                movieRecorder = new MovieRecorder();
                movieRecorder.init(mSurfaceView);

                bt_startVideo.setVisibility(View.GONE);
                bt_stopVideo.setVisibility(View.VISIBLE);
                movieRecorder.startVideo();
                break;
            case R.id.bt_stopVideo:
                bt_startVideo.setVisibility(View.VISIBLE);
                bt_stopVideo.setVisibility(View.GONE);
                movieRecorder.stopVideo();
                ll_imgshow.setVisibility(View.VISIBLE);
                ll_imgtake.setVisibility(View.GONE);
                rl_video.setVisibility(View.VISIBLE);
                iv_show.setVisibility(View.GONE);
                movieRecorder.destory();
                break;
            case R.id.ib_video:
                Toast.makeText(getApplicationContext(), "播放", Toast.LENGTH_SHORT).show();
                movieRecorder.palyVedio(getApplicationContext());
                break;
            case R.id.bt_picture:
                Toast.makeText(getApplicationContext(), "录像", Toast.LENGTH_SHORT).show();
                bt_picture.setVisibility(View.GONE);
                bt_video.setVisibility(View.VISIBLE);
                bt_takepicture.setVisibility(View.GONE);
                bt_startVideo.setVisibility(View.VISIBLE);
                bt_stopVideo.setVisibility(View.GONE);
                break;
            case R.id.bt_video:
                Toast.makeText(getApplicationContext(), "拍照", Toast.LENGTH_SHORT).show();
                bt_picture.setVisibility(View.VISIBLE);
                bt_video.setVisibility(View.GONE);
                bt_takepicture.setVisibility(View.VISIBLE);
                bt_startVideo.setVisibility(View.GONE);
                bt_stopVideo.setVisibility(View.GONE);
                break;
            case R.id.bt_trans:
                mCameraDevice.close();
                TakePicture.this.mCameraDevice = null;
                if (mCameraID.equals("0"))
                    mCameraID = "" + CameraCharacteristics.LENS_FACING_BACK;//hou
                else mCameraID = "" + CameraCharacteristics.LENS_FACING_FRONT;//hou
                initCamera2();
                break;
            case R.id.bt_submit:
                submit();
                break;
        }
    }

    public void submit() {
        showProgressDialog("请稍候!", "正在提交数据...");
        disease = et_disease.getText().toString().trim();

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    String log = SendImage.send(getApplicationContext(), disease);
                    Message msg = new Message();
                    msg.what = 1;
                    msg.obj = log;
                    handler.sendMessage(msg);
                } catch (Exception e) {
                    e.printStackTrace();
                    Message msg = new Message();
                    msg.what = 0;
                    handler.sendMessage(msg);
                }

            }
        }).start();

    }

    private Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 1:
                    String info = (String) msg.obj;
                    if (info.equals("success")) {

                        Toast.makeText(getApplicationContext(), "数据已提交", Toast.LENGTH_SHORT).show();
                        Intent intent = new Intent(getApplicationContext(), Frament.class);
                        startActivity(intent);
                        finish();
                    }
                    break;
                case 0:
                    progressDialog.dismiss();
                    Toast.makeText(getApplicationContext(), "连接网络失败,请检查网络是否连接", Toast.LENGTH_SHORT)
                            .show();
                    break;
            }
        }
    };
    private ProgressDialog progressDialog;
    public void showProgressDialog(String title, String message) {
        if (progressDialog == null) {
            progressDialog = ProgressDialog.show(this, title, message, true, false);
        } else if (progressDialog.isShowing()) {
            progressDialog.setTitle(title);
            progressDialog.setMessage(message);
        }
        progressDialog.setCancelable(false);
        progressDialog.show();
    }

    private void openAlbum() {
        Intent intent = new Intent("android.intent.action.GET_CONTENT");
        intent.setType("image/*");
        startActivityForResult(intent, 2);
    }

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {

            case 2:
                if (resultCode == RESULT_OK) {
                    if (Build.VERSION.SDK_INT >= 19) {
                        handleImageOnKitKat(data);
                    } else {
                        handleImageBeforeKitKat(data);
                    }
                }
                break;
            default:
                break;
        }
    }


    @TargetApi(19)
    private void handleImageOnKitKat(Intent data) {
        String imagePath = null;
        Uri uri = data.getData();
        if (DocumentsContract.isDocumentUri(this, uri)) {
            String docId = DocumentsContract.getDocumentId(uri);
            if ("com.android.providers.media.documents".equals(uri.getAuthority())) {
                String id = docId.split(":")[1];
                String selection = MediaStore.Images.Media._ID + "=" + id;
                imagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection);
            } else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) {
                Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(docId));
                imagePath = getImagePath(contentUri, null);
            }
        } else if ("content".equalsIgnoreCase(uri.getScheme())) {
            imagePath = getImagePath(uri, null);
        } else if ("file".equalsIgnoreCase(uri.getScheme())) {
            imagePath = uri.getPath();
        }
        displayImage(imagePath);
    }

    //如果是4.4以下版本直接传入
    private void handleImageBeforeKitKat(Intent data) {
        Uri uri = data.getData();
        String imagePath = getImagePath(uri, null);
        displayImage(imagePath);
    }

    //获取图片真实路径
    private String getImagePath(Uri uri, String selection) {
        String path = null;
        //获取内容解析器查询
        Cursor cursor = getContentResolver().query(uri, null, selection, null, null);
        if (cursor != null) {
            if (cursor.moveToFirst()) {
                path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
            }
            cursor.close();
        }
        return path;
    }

    //显示图片
    private void displayImage(String imagePath) {
        if (imagePath != null) {
            SendImage.imagePath = imagePath;
            Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
            ll_imgshow.setVisibility(View.VISIBLE);
            ll_imgtake.setVisibility(View.GONE);
            rl_video.setVisibility(View.GONE);
            iv_show.setVisibility(View.VISIBLE);
            iv_show.setImageBitmap(bitmap);
        } else {
            Toast.makeText(this, "获取图片失败", Toast.LENGTH_SHORT).show();
        }
    }

    private void takePicture() {
        if (mCameraDevice == null) return;
        final CaptureRequest.Builder captureRequestBuilder;
        try {
            captureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
            captureRequestBuilder.addTarget(mImageReader.getSurface());
            captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
            captureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
            int rotation = getWindowManager().getDefaultDisplay().getRotation();
            captureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
            CaptureRequest mCaptureRequest = captureRequestBuilder.build();
            mCameraCaptureSession.capture(mCaptureRequest, null, childHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }

    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            Intent intent = new Intent(this, Frament.class);
            startActivity(intent);
            finish();
        }
        return super.onKeyDown(keyCode, event);
    }

    @SuppressLint("InlinedApi")
    private void initMediaRecorder() {
        mr = new MediaRecorder();
        mr.setAudioSource(MediaRecorder.AudioSource.MIC);
        if (Build.VERSION.SDK_INT > 10) {
            mr.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
            mr.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
        } else {
            mr.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);
            mr.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
        }
        mr.setOnErrorListener(new MediaRecorder.OnErrorListener() {

            @Override
            public void onError(MediaRecorder mr, int what, int extra) {
            }
        });
        mr.setOnInfoListener(new MediaRecorder.OnInfoListener() {

            @Override
            public void onInfo(MediaRecorder mr, int what, int extra) {
            }
        });

    }

    private void initMediaPlayer() {
        mp = new MediaPlayer();
        mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {

            @Override
            public void onCompletion(MediaPlayer mp) {
                btStartPlay.setEnabled(true);
                btStartRecord.setEnabled(true);
            }
        });
        mp.setOnErrorListener(new MediaPlayer.OnErrorListener() {

            @Override
            public boolean onError(MediaPlayer mp, int what, int extra) {
                return false;
            }
        });
        mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {

            @Override
            public void onPrepared(MediaPlayer mp) {
                btStartRecord.setEnabled(false);
                btStartPlay.setEnabled(false);
            }
        });
        mp.setOnInfoListener(new MediaPlayer.OnInfoListener() {

            @Override
            public boolean onInfo(MediaPlayer mp, int what, int extra) {
                return false;
            }
        });
    }

    SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd-hh-mm-ss");


    class startRecordListener implements View.OnLongClickListener {
        @Override
        public boolean onLongClick(View v) {
            try {
                initMediaRecorder();
                curVoiveFile = File.createTempFile(sdf.format(new Date()), ".arm", voiceDir);
                System.out.println("nihao" + curVoiveFile.getAbsolutePath());
                SendImage.voicePath = curVoiveFile.getAbsolutePath();
                mr.setOutputFile(curVoiveFile.getAbsolutePath());
                mr.prepare();
                mr.start();
                updateMicStatus();
            } catch (IllegalStateException e) {
                e.printStackTrace();
//                stopRecord(v);
                initMediaRecorder();
            } catch (IOException e) {
                e.printStackTrace();
//                stopRecord(v);
                initMediaRecorder();
            }
            return false;
            //KeyPoint：setOnLongClickListener中return的值决定是否在长按后再加一个短按动作，true为不加短按,false为加入短按
        }
    }

    //短按停止录音，直接点击短按无效
    class stopRecordListener implements View.OnClickListener {
        @Override
        public void onClick(View v) {
            mr.stop();
            mr.reset();
            mr.release();
            mr = null;
            btStartRecord.setEnabled(true);
            btStartPlay.setEnabled(true);
            mHandler.removeCallbacks(mUpdateMicStatusTimer);
        }
    }

    public void startPlay(View v) {
        if (curVoiveFile == null || !curVoiveFile.exists()) {
            return;
        }
        if (mp == null) {
            initMediaPlayer();
        }
        try {
            mp.setDataSource(curVoiveFile.getAbsolutePath());
            mp.prepare();
            mp.start();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
            stopPlay(v);
        } catch (SecurityException e) {
            e.printStackTrace();
            stopPlay(v);
        } catch (IllegalStateException e) {
            e.printStackTrace();
            stopPlay(v);
        } catch (IOException e) {
            e.printStackTrace();
            stopPlay(v);
        }
    }

    public void stopPlay(View v) {
        mp.stop();
        mp.reset();
        mp.release();
        mp = null;
    }


    //遍历删除文件
    private void delFile(File file) {
        if (file.isDirectory()) {
            for (File f : file.listFiles()) {
                delFile(f);
            }
        } else if (file.isFile()) {
            file.delete();
        }
    }

    private final Handler mHandler = new Handler();
    private Runnable mUpdateMicStatusTimer = new Runnable() {
        public void run() {
            updateMicStatus();
        }
    };
    /**
     * 更新话筒状态
     */
    private int BASE = 150;
    private int SPACE = 100;// 间隔取样时间

    private void updateMicStatus() {
        if (mr != null) {
            int maxAmpl = mr.getMaxAmplitude();
            int ratio = (int) maxAmpl / BASE;
            int db = 0;// 分贝
            if (ratio > 1)
                db = (int) (20 * Math.log10(ratio));
            iv.setImageDrawable(micImages[db / 7]);
            mHandler.postDelayed(mUpdateMicStatusTimer, SPACE);
        }
    }

//    @Override
//    protected void onDestroy() {
//        movieRecorder.destory();
//        super.onDestroy();
//    }
}
